package com.example.seckill.service;

import com.example.seckill.mapper.SeckillMapper;
import com.example.seckill.result.SeckillResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SeckillService {
    
    // 每台服务器2个信号量，控制数据库并发访问
    private final Semaphore semaphore = new Semaphore(2);
    
    @Autowired
    private SeckillMapper seckillMapper;
    
    /**
     * 秒杀主流程
     */
    public SeckillResult seckill(Long userId, Long productId) {
        log.info("用户{}开始秒杀商品{}", userId, productId);
        
        boolean acquired = false;
        try {
            // 尝试获取信号量，超时时间100ms
            acquired = semaphore.tryAcquire(100, TimeUnit.MILLISECONDS);
            
            if (!acquired) {
                log.info("用户{}获取信号量失败，直接返回", userId);
                return SeckillResult.fail("系统繁忙，请稍后重试");
            }
            
            log.info("用户{}获取信号量成功，开始数据库操作", userId);
            // 只有获得信号量的线程才能执行数据库操作
            return doSeckill(userId, productId);
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("用户{}秒杀被中断", userId, e);
            return SeckillResult.fail("请求被中断");
        } finally {
            if (acquired) {
                semaphore.release();
                log.info("用户{}释放信号量", userId);
            }
        }
    }
    
    /**
     * 执行具体的秒杀逻辑
     */
    private SeckillResult doSeckill(Long userId, Long productId) {
        try {
            // 关键步骤1：原子性减库存
            int updated = seckillMapper.updateStock(productId);
            
            if (updated > 0) {
                log.info("用户{}减库存成功", userId);
                
                // 关键步骤2：创建订单
                seckillMapper.createOrder(userId, productId);
                log.info("用户{}创建订单成功", userId);
                
                return SeckillResult.success("恭喜您，秒杀成功！");
            } else {
                log.info("用户{}减库存失败，商品已售完", userId);
                return SeckillResult.fail("很遗憾，商品已被抢完");
            }
            
        } catch (DuplicateKeyException e) {
            log.info("用户{}重复下单", userId);
            return SeckillResult.fail("您已经参与过此次秒杀");
        } catch (Exception e) {
            log.error("用户{}秒杀异常", userId, e);
            return SeckillResult.fail("秒杀失败，请重试");
        }
    }
    
    /**
     * 查询当前库存（用于前端显示）
     */
    public int getCurrentStock(Long productId) {
        return seckillMapper.getStock(productId);
    }
}
